package sf.dsl.example;

import sf.database.jdbc.sql.SQLParameter;
import sf.tools.StringUtils;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Defines a positioned flag in a Query for customization of query serialization
 * @see com.querydsl.core.QueryFlag
 */
public class SQLFlag implements Serializable {
    protected Map<Position, String> sqlFlags = null;

    /**
     * The different {@code SQLFlag} positions
     */
    public enum Position {

        /**
         * WITH part (used in SQL)
         */
        WITH,

        /**
         * Start of the query
         */
        START,

        /**
         * Override for the first element (e.g SELECT, INSERT)
         */
        START_OVERRIDE,

        /**
         * After the first element (after select)
         */
        AFTER_SELECT,

        /**
         * After the projection (after select ...)
         */
        AFTER_PROJECTION,

        /**
         * Before the filter conditions (where)
         */
        BEFORE_FILTERS,

        /**
         * After the filter conditions (where)
         */
        AFTER_FILTERS,

        /**
         * Before group by
         */
        BEFORE_GROUP_BY,

        /**
         * After group by
         */
        AFTER_GROUP_BY,

        /**
         * Before having
         */
        BEFORE_HAVING,

        /**
         * After having
         */
        AFTER_HAVING,

        /**
         * Before order (by)
         */
        BEFORE_ORDER,

        /**
         * After order (by)
         */
        AFTER_ORDER,

        /**
         * After all other tokens
         */
        END

    }

    public void addFlag(SQLFlag.Position position, String flag) {
        if (sqlFlags == null) {
            sqlFlags = new LinkedHashMap<>();
        }
        this.sqlFlags.put(position, flag);
    }

    public String getPosition(Position position) {
        if (sqlFlags != null) {
            String flag = sqlFlags.get(position);
            if (StringUtils.isNotBlank(flag)) {
                return flag;
            }
        }
        return "";
    }

    public void toSql(Position position, StringBuilder sql, List<SQLParameter> list) {
        sql.append(getPosition(position));
    }

    public Map<Position, String> getSqlFlags() {
        return sqlFlags;
    }

    public void setSqlFlags(Map<Position, String> sqlFlags) {
        this.sqlFlags = sqlFlags;
    }
}
